home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / io / File.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  55.0 KB  |  1,413 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)File.java    1.81 98/11/09
  3.  *
  4.  * Copyright 1994-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.io;
  16.  
  17. import java.net.URL;
  18. import java.net.MalformedURLException;
  19. import java.util.ArrayList;
  20. import java.util.Map;
  21. import java.util.Hashtable;
  22. import java.util.Random;
  23. import java.security.AccessController;
  24. import java.security.AccessControlException;
  25. import sun.security.action.GetPropertyAction;
  26.  
  27.  
  28. /**
  29.  * An abstract representation of file and directory pathnames.
  30.  *
  31.  * <p> User interfaces and operating systems use system-dependent <em>pathname
  32.  * strings</em> to name files and directories.  This class presents an
  33.  * abstract, system-independent view of hierarchical pathnames.  An
  34.  * <em>abstract pathname</em> has two components:
  35.  *
  36.  * <ol>
  37.  * <li> An optional system-dependent <em>prefix</em> string,<br>
  38.  *      such as a disk-drive specifier, <code>"/"</code> for the UNIX root
  39.  *      directory, or <code>"\\"</code> for a Win32 UNC pathname, and
  40.  * <li> A sequence of zero or more string <em>names</em>.
  41.  * </ol>
  42.  *
  43.  * Each name in an abstract pathname except for the last denotes a directory;
  44.  * the last name may denote either a directory or a file.  The <em>empty</em>
  45.  * abstract pathname has no prefix and an empty name sequence.
  46.  *
  47.  * <p> The conversion of a pathname string to or from an abstract pathname is
  48.  * inherently system-dependent.  When an abstract pathname is converted into a
  49.  * pathname string, each name is separated from the next by a single copy of
  50.  * the default <em>separator character</em>.  The default name-separator
  51.  * character is defined by the system property <code>file.separator</code>, and
  52.  * is made available in the public static fields <code>{@link
  53.  * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
  54.  * When a pathname string is converted into an abstract pathname, the names
  55.  * within it may be separated by the default name-separator character or by any
  56.  * other name-separator character that is supported by the underlying system.
  57.  *
  58.  * <p> A pathname, whether abstract or in string form, may be either
  59.  * <em>absolute</em> or <em>relative</em>.  An absolute pathname is complete in
  60.  * that no other information is required in order to locate the file that it
  61.  * denotes.  A relative pathname, in contrast, must be interpreted in terms of
  62.  * information taken from some other pathname.  By default the classes in the
  63.  * <code>java.io</code> package always resolve relative pathnames against the
  64.  * current user directory.  This directory is named by the system property
  65.  * <code>user.dir</code>, and is typically the directory in which the Java
  66.  * virtual machine was invoked.
  67.  *
  68.  * <p> The prefix concept is used to handle root directories on UNIX platforms,
  69.  * and drive specifiers, root directories and UNC pathnames on Win32 platforms,
  70.  * as follows:
  71.  *
  72.  * <ul>
  73.  *
  74.  * <li> For UNIX platforms, the prefix of an absolute pathname is always
  75.  * <code>"/"</code>.  Relative pathnames have no prefix.  The abstract pathname
  76.  * denoting the root directory has the prefix <code>"/"</code> and an empty
  77.  * name sequence.
  78.  *
  79.  * <li> For Win32 platforms, the prefix of a pathname that contains a drive
  80.  * specifier consists of the drive letter followed by <code>":"</code> and
  81.  * possibly followed by <code>"\"</code> if the pathname is absolute.  The
  82.  * prefix of a UNC pathname is <code>"\\"</code>; the hostname and the share
  83.  * name are the first two names in the name sequence.  A relative pathname that
  84.  * does not specify a drive has no prefix.
  85.  *
  86.  * </ul>
  87.  *
  88.  * <p> Instances of the <code>File</code> class are immutable; that is, once
  89.  * created, the abstract pathname represented by a <code>File</code> object
  90.  * will never change.
  91.  *
  92.  * @version 1.79, 98/08/18
  93.  * @author  unascribed
  94.  * @since   JDK1.0
  95.  */
  96.  
  97. public class File implements java.io.Serializable, Comparable {
  98.  
  99.     /**
  100.      * The FileSystem object representing the platform's local file system.
  101.      */
  102.     static private FileSystem fs = FileSystem.getFileSystem();
  103.  
  104.     /**
  105.      * This abstract pathname's normalized pathname string.  A normalized
  106.      * pathname string uses the default name-separator character and does not
  107.      * contain any duplicate or redundant separators.
  108.      *
  109.      * @serial
  110.      */
  111.     private String path;
  112.  
  113.     /**
  114.      * The length of this abstract pathname's prefix, or zero if it has no
  115.      * prefix.
  116.      */
  117.     private transient int prefixLength;
  118.  
  119.     /**
  120.      * Returns the length of this abstract pathname's prefix.
  121.      * For use by FileSystem classes.
  122.      */
  123.     int getPrefixLength() {
  124.     return prefixLength;
  125.     }
  126.  
  127.     /**
  128.      * The system-dependent default name-separator character.  This field is
  129.      * initialized to contain the first character of the value of the system
  130.      * property <code>file.separator</code>.  On UNIX systems the value of this
  131.      * field is <code>'/'</code>; on Win32 systems it is <code>'\'</code>.
  132.      *
  133.      * @see     java.lang.System#getProperty(java.lang.String)
  134.      */
  135.     public static final char separatorChar = fs.getSeparator();
  136.  
  137.     /**
  138.      * The system-dependent default name-separator character, represented as a
  139.      * string for convenience.  This string contains a single character, namely
  140.      * <code>{@link #separatorChar}</code>.
  141.      */
  142.     public static final String separator = "" + separatorChar;
  143.  
  144.     /**
  145.      * The system-dependent path-separator character.  This field is
  146.      * initialized to contain the first character of the value of the system
  147.      * property <code>path.separator</code>.  This character is used to
  148.      * separate filenames in a sequence of files given as a <em>path list</em>.
  149.      * On UNIX systems, this character is <code>':'</code>; on Win32 systems it
  150.      * is <code>';'</code>.
  151.      *
  152.      * @see     java.lang.System#getProperty(java.lang.String)
  153.      */
  154.     public static final char pathSeparatorChar = fs.getPathSeparator();
  155.  
  156.     /**
  157.      * The system-dependent path-separator character, represented as a string
  158.      * for convenience.  This string contains a single character, namely
  159.      * <code>{@link #pathSeparatorChar}</code>.
  160.      */
  161.     public static final String pathSeparator = "" + pathSeparatorChar;
  162.  
  163.  
  164.     /* -- Constructors -- */
  165.  
  166.     /**
  167.      * Internal constructor for already-normalized pathname strings.
  168.      */
  169.     private File(String pathname, int prefixLength) {
  170.     this.path = pathname;
  171.     this.prefixLength = prefixLength;
  172.     }
  173.  
  174.     /**
  175.      * Creates a new <code>File</code> instance by converting the given
  176.      * pathname string into an abstract pathname.  If the given string is
  177.      * the empty string, then the result is the empty abstract pathname.
  178.      *
  179.      * @param   pathname  A pathname string
  180.      * @throws  NullPointerException
  181.      *          If the <code>pathname</code> argument is <code>null</code>
  182.      */
  183.     public File(String pathname) {
  184.     if (pathname == null) {
  185.         throw new NullPointerException();
  186.     }
  187.     this.path = fs.normalize(pathname);
  188.     this.prefixLength = fs.prefixLength(this.path);
  189.     }
  190.  
  191.     /* Note: The two-argument File constructors do not interpret an empty
  192.        parent abstract pathname as the current user directory.  An empty parent
  193.        instead causes the child to be resolved against the system-dependent
  194.        directory defined by the FileSystem.getDefaultParent method.  On Unix
  195.        this default is "/", while on Win32 it is "\\".  This is required for
  196.        compatibility with the original behavior of this class. */
  197.  
  198.     /**
  199.      * Creates a new <code>File</code> instance from a parent pathname string
  200.      * and a child pathname string.
  201.      *
  202.      * <p> If <code>parent</code> is <code>null</code> then the new
  203.      * <code>File</code> instance is created as if by invoking the
  204.      * single-argument <code>File</code> constructor on the given
  205.      * <code>child</code> pathname string.
  206.      *
  207.      * <p> Otherwise the <code>parent</code> pathname string is taken to denote
  208.      * a directory, and the <code>child</code> pathname string is taken to
  209.      * denote either a directory or a file.  If the <code>child</code> pathname
  210.      * string is absolute then it is converted into a relative pathname in a
  211.      * system-dependent way.  If <code>parent</code> is the empty string then
  212.      * the new <code>File</code> instance is created by converting
  213.      * <code>child</code> into an abstract pathname and resolving the result
  214.      * against a system-dependent default directory.  Otherwise each pathname
  215.      * string is converted into an abstract pathname and the child abstract
  216.      * pathname is resolved against the parent.
  217.      *
  218.      * @param   parent  The parent pathname string
  219.      * @param   child   The child pathname string
  220.      * @throws  NullPointerException
  221.      *          If <code>child</code> is <code>null</code>
  222.      */
  223.     public File(String parent, String child) {
  224.     if (child == null) {
  225.         throw new NullPointerException();
  226.     }
  227.     if (parent != null) {
  228.         if (parent.equals("")) {
  229.         this.path = fs.resolve(fs.getDefaultParent(),
  230.                        fs.normalize(child));
  231.         } else {
  232.         this.path = fs.resolve(fs.normalize(parent),
  233.                        fs.normalize(child));
  234.         }
  235.     } else {
  236.         this.path = fs.normalize(child);
  237.     }
  238.     this.prefixLength = fs.prefixLength(this.path);
  239.     }
  240.  
  241.     /**
  242.      * Creates a new <code>File</code> instance from a parent abstract
  243.      * pathname and a child pathname string.
  244.      *
  245.      * <p> If <code>parent</code> is <code>null</code> then the new
  246.      * <code>File</code> instance is created as if by invoking the
  247.      * single-argument <code>File</code> constructor on the given
  248.      * <code>child</code> pathname string.
  249.      *
  250.      * <p> Otherwise the <code>parent</code> abstract pathname is taken to
  251.      * denote a directory, and the <code>child</code> pathname string is taken
  252.      * to denote either a directory or a file.  If the <code>child</code>
  253.      * pathname string is absolute then it is converted into a relative
  254.      * pathname in a system-dependent way.  If <code>parent</code> is the empty
  255.      * abstract pathname then the new <code>File</code> instance is created by
  256.      * converting <code>child</code> into an abstract pathname and resolving
  257.      * the result against a system-dependent default directory.  Otherwise each
  258.      * pathname string is converted into an abstract pathname and the child
  259.      * abstract pathname is resolved against the parent.
  260.      *
  261.      * @param   parent  The parent abstract pathname
  262.      * @param   child   The child pathname string
  263.      * @throws  NullPointerException
  264.      *          If <code>child</code> is <code>null</code>
  265.      */
  266.     public File(File parent, String child) {
  267.     if (child == null) {
  268.         throw new NullPointerException();
  269.     }
  270.     if (parent != null) {
  271.         if (parent.path.equals("")) {
  272.         this.path = fs.resolve(fs.getDefaultParent(),
  273.                        fs.normalize(child));
  274.         } else {
  275.         this.path = fs.resolve(parent.path,
  276.                        fs.normalize(child));
  277.         }
  278.     } else {
  279.         this.path = fs.normalize(child);
  280.     }
  281.     this.prefixLength = fs.prefixLength(this.path);
  282.     }
  283.  
  284.  
  285.     /* -- Path-component accessors -- */
  286.  
  287.     /**
  288.      * Returns the name of the file or directory denoted by this abstract
  289.      * pathname.  This is just the last name in the pathname's name
  290.      * sequence.  If the pathname's name sequence is empty, then the empty
  291.      * string is returned.
  292.      *
  293.      * @return  The name of the file or directory denoted by this abstract
  294.      *          pathname, or the empty string if this pathname's name sequence
  295.      *          is empty
  296.      */
  297.     public String getName() {
  298.     int index = path.lastIndexOf(separatorChar);
  299.     if (index < prefixLength) return path.substring(prefixLength);
  300.     return path.substring(index + 1);
  301.     }
  302.  
  303.     /**
  304.      * Returns the pathname string of this abstract pathname's parent, or
  305.      * <code>null</code> if this pathname does not name a parent directory.
  306.      *
  307.      * <p> The <em>parent</em> of an abstract pathname consists of the
  308.      * pathname's prefix, if any, and each name in the pathname's name
  309.      * sequence except for the last.  If the name sequence is empty then
  310.      * the pathname does not name a parent directory.
  311.      *
  312.      * @return  The pathname string of the parent directory named by this
  313.      *          abstract pathname, or <code>null</code> if this pathname
  314.      *          does not name a parent
  315.      */
  316.     public String getParent() {
  317.     int index = path.lastIndexOf(separatorChar);
  318.     if (index < prefixLength) {
  319.         if ((prefixLength > 0) && (path.length() > prefixLength))
  320.         return path.substring(0, prefixLength);
  321.         return null;
  322.     }
  323.     return path.substring(0, index);
  324.     }
  325.  
  326.     /**
  327.      * Returns the abstract pathname of this abstract pathname's parent,
  328.      * or <code>null</code> if this pathname does not name a parent
  329.      * directory.
  330.      *
  331.      * <p> The <em>parent</em> of an abstract pathname consists of the
  332.      * pathname's prefix, if any, and each name in the pathname's name
  333.      * sequence except for the last.  If the name sequence is empty then
  334.      * the pathname does not name a parent directory.
  335.      *
  336.      * @return  The abstract pathname of the parent directory named by this
  337.      *          abstract pathname, or <code>null</code> if this pathname
  338.      *          does not name a parent
  339.      *
  340.      * @since JDK1.2
  341.      */
  342.     public File getParentFile() {
  343.     String p = this.getParent();
  344.     if (p == null) return null;
  345.     return new File(p, this.prefixLength);
  346.     }
  347.  
  348.     /**
  349.      * Converts this abstract pathname into a pathname string.  The resulting
  350.      * string uses the {@link #separator default name-separator character} to
  351.      * separate the names in the name sequence.
  352.      *
  353.      * @return  The string form of this abstract pathname
  354.      */
  355.     public String getPath() {
  356.     return path;
  357.     }
  358.  
  359.  
  360.     /* -- Path operations -- */
  361.  
  362.     /**
  363.      * Tests whether this abstract pathname is absolute.  The definition of
  364.      * absolute pathname is system dependent.  On UNIX systems, a pathname is
  365.      * absolute if its prefix is <code>"/"</code>.  On Win32 systems, a
  366.      * pathname is absolute if its prefix is a drive specifier followed by
  367.      * <code>"\\"</code>, or if its prefix is <code>"\\"</code>.
  368.      *
  369.      * @return  <code>true</code> if this abstract pathname is absolute,
  370.      *          <code>false</code> otherwise
  371.      */
  372.     public boolean isAbsolute() {
  373.     return fs.isAbsolute(this);
  374.     }
  375.  
  376.     /**
  377.      * Returns the absolute pathname string of this abstract pathname.
  378.      *
  379.      * <p> If this abstract pathname is already absolute, then the pathname
  380.      * string is simply returned as if by the <code>{@link #getPath}</code>
  381.      * method.  If this abstract pathname is the empty abstract pathname then
  382.      * the pathname string of the current user directory, which is named by the
  383.      * system property <code>user.dir</code>, is returned.  Otherwise this
  384.      * pathname is resolved in a system-dependent way.  On UNIX systems, a
  385.      * relative pathname is made absolute by resolving it against the current
  386.      * user directory.  On Win32 systems, a relative pathname is made absolute
  387.      * by resolving it against the current directory of the drive named by the
  388.      * pathname, if any; if not, it is resolved against the current user
  389.      * directory.
  390.      *
  391.      * @return  The absolute pathname string denoting the same file or
  392.      *          directory as this abstract pathname
  393.      *
  394.      * @see     java.io.File#isAbsolute()
  395.      */
  396.     public String getAbsolutePath() {
  397.     return fs.resolve(this);
  398.     }
  399.  
  400.     /**
  401.      * Returns the absolute form of this abstract pathname.  Equivalent to
  402.      * <code>new File(this.{@link #getAbsolutePath}())</code>.
  403.      *
  404.      * @return  The absolute abstract pathname denoting the same file or
  405.      *          directory as this abstract pathname
  406.      *
  407.      * @since JDK1.2
  408.      */
  409.     public File getAbsoluteFile() {
  410.     return new File(getAbsolutePath());
  411.     }
  412.  
  413.     /**
  414.      * Returns the canonical pathname string of this abstract pathname.
  415.      *
  416.      * <p> The precise definition of canonical form is system-dependent, but
  417.      * canonical forms are always absolute.  Thus if this abstract pathname is
  418.      * relative it will be converted to absolute form as if by the <code>{@link
  419.      * #getAbsoluteFile}</code> method.
  420.      *
  421.      * <p> Every pathname that denotes an existing file or directory has a
  422.      * unique canonical form.  Every pathname that denotes a nonexistent file
  423.      * or directory also has a unique canonical form.  The canonical form of
  424.      * the pathname of a nonexistent file or directory may be different from
  425.      * the canonical form of the same pathname after the file or directory is
  426.      * created.  Similarly, the canonical form of the pathname of an existing
  427.      * file or directory may be different from the canonical form of the same
  428.      * pathname after the file or directory is deleted.
  429.      *
  430.      * @return  The canonical pathname string denoting the same file or
  431.      *          directory as this abstract pathname
  432.      *
  433.      * @throws  IOException
  434.      *          If an I/O error occurs, which is possible because the
  435.      *          construction of the canonical pathname may require
  436.      *          filesystem queries
  437.      *
  438.      * @since   JDK1.1
  439.      */
  440.     public String getCanonicalPath() throws IOException {
  441.     return fs.canonicalize(fs.resolve(this));
  442.     }
  443.  
  444.     /**
  445.      * Returns the canonical form of this abstract pathname.  Equivalent to
  446.      * <code>new File(this.{@link #getCanonicalPath}())</code>.
  447.      *
  448.      * @return  The canonical pathname string denoting the same file or
  449.      *          directory as this abstract pathname
  450.      *
  451.      * @throws  IOException
  452.      *          If an I/O error occurs, which is possible because the
  453.      *          construction of the canonical pathname may require
  454.      *          filesystem queries
  455.      *
  456.      * @since JDK1.2
  457.      */
  458.     public File getCanonicalFile() throws IOException {
  459.     return new File(getCanonicalPath());
  460.     }
  461.  
  462.     /**
  463.      * Converts this abstract pathname into a <code>file:</code> URL.  The
  464.      * exact form of the URL is system-dependent.  If it can be determined that
  465.      * the file denoted by this abstract pathname is a directory, then the
  466.      * resulting URL will end with a slash.
  467.      *
  468.      * @see     java.net.URL
  469.      * @since   JDK1.2
  470.      */
  471.     public URL toURL() throws MalformedURLException {
  472.     String path = getAbsolutePath();
  473.     if (File.separatorChar != '/') {
  474.         path = path.replace(File.separatorChar, '/');
  475.     }
  476.     if (!path.startsWith("/")) {
  477.         path = "/" + path;
  478.     }
  479.     if (!path.endsWith("/") && isDirectory()) {
  480.         path = path + "/";
  481.     }
  482.     return new URL("file", "", path);
  483.     }
  484.  
  485.  
  486.     /* -- Attribute accessors -- */
  487.  
  488.     /**
  489.      * Tests whether the application can read the file denoted by this
  490.      * abstract pathname.
  491.      *
  492.      * @return  <code>true</code> if and only if the file specified by this
  493.      *          abstract pathname exists <em>and</em> can be read by the
  494.      *          application; <code>false</code> otherwise
  495.      *
  496.      * @throws  SecurityException
  497.      *          If a security manager exists and its <code>{@link
  498.      *          java.lang.SecurityManager#checkRead}</code> method denies
  499.      *          read access to the file
  500.      */
  501.     public boolean canRead() {
  502.     SecurityManager security = System.getSecurityManager();
  503.     if (security != null) {
  504.         security.checkRead(path);
  505.     }
  506.     return fs.checkAccess(this, false);
  507.     }
  508.  
  509.     /**
  510.      * Tests whether the application can modify to the file denoted by this
  511.      * abstract pathname.
  512.      *
  513.      * @return  <code>true</code> if and only if the file system actually
  514.      *          contains a file denoted by this abstract pathname <em>and</em>
  515.      *          the application is allowed to write to the file;
  516.      *          <code>false</code> otherwise.
  517.      *
  518.      * @throws  SecurityException
  519.      *          If a security manager exists and its <code>{@link
  520.      *          java.lang.SecurityManager#checkWrite}</code> method denies
  521.      *          write access to the file
  522.      */
  523.     public boolean canWrite() {
  524.     SecurityManager security = System.getSecurityManager();
  525.     if (security != null) {
  526.         security.checkWrite(path);
  527.     }
  528.     return fs.checkAccess(this, true);
  529.     }
  530.  
  531.     /**
  532.      * Tests whether the file denoted by this abstract pathname exists.
  533.      *
  534.      * @return  <code>true</code> if and only if the file denoted by this
  535.      *          abstract pathname exists; <code>false</code> otherwise
  536.      *
  537.      * @throws  SecurityException
  538.      *          If a security manager exists and its <code>{@link
  539.      *          java.lang.SecurityManager#checkRead}</code> method denies
  540.      *          read access to the file
  541.      */
  542.     public boolean exists() {
  543.     SecurityManager security = System.getSecurityManager();
  544.     if (security != null) {
  545.         security.checkRead(path);
  546.     }
  547.     return ((fs.getBooleanAttributes(this) & FileSystem.BA_EXISTS) != 0);
  548.     }
  549.  
  550.     /**
  551.      * Tests whether the file denoted by this abstract pathname is a
  552.      * directory.
  553.      *
  554.      * @return <code>true</code> if and only if the file denoted by this
  555.      *          abstract pathname exists <em>and</em> is a directory;
  556.      *          <code>false</code> otherwise
  557.      *
  558.      * @throws  SecurityException
  559.      *          If a security manager exists and its <code>{@link
  560.      *          java.lang.SecurityManager#checkRead}</code> method denies
  561.      *          read access to the file
  562.      */
  563.     public boolean isDirectory() {
  564.     SecurityManager security = System.getSecurityManager();
  565.     if (security != null) {
  566.         security.checkRead(path);
  567.     }
  568.     return ((fs.getBooleanAttributes(this) & FileSystem.BA_DIRECTORY)
  569.         != 0);
  570.     }
  571.  
  572.     /**
  573.      * Tests whether the file denoted by this abstract pathname is a normal
  574.      * file.  A file is <em>normal</em> if it is not a directory and, in
  575.      * addition, satisfies other system-dependent criteria.  Any non-directory
  576.      * file created by a Java application is guaranteed to be a normal file.
  577.      *
  578.      * @return  <code>true</code> if and only if the file denoted by this
  579.      *          abstract pathname exists <em>and</em> is a normal file;
  580.      *          <code>false</code> otherwise
  581.      *
  582.      * @throws  SecurityException
  583.      *          If a security manager exists and its <code>{@link
  584.      *          java.lang.SecurityManager#checkRead}</code> method denies
  585.      *          read access to the file
  586.      */
  587.     public boolean isFile() {
  588.     SecurityManager security = System.getSecurityManager();
  589.     if (security != null) {
  590.         security.checkRead(path);
  591.     }
  592.     return ((fs.getBooleanAttributes(this) & FileSystem.BA_REGULAR) != 0);
  593.     }
  594.  
  595.     /**
  596.      * Tests whether the file named by this abstract pathname is a hidden
  597.      * file.  The exact definition of <em>hidden</em> is system-dependent.  On
  598.      * UNIX systems, a file is considered to be hidden if its name begins with
  599.      * a period character (<code>'.'</code>).  On Win32 systems, a file is
  600.      * considered to be hidden if it has been marked as such in the filesystem.
  601.      *
  602.      * @return  <code>true</code> if and only if the file denoted by this
  603.      *          abstract pathname is hidden according to the conventions of the
  604.      *          underlying platform
  605.      *
  606.      * @throws  SecurityException
  607.      *          If a security manager exists and its <code>{@link
  608.      *          java.lang.SecurityManager#checkRead}</code> method denies
  609.      *          read access to the file
  610.      *
  611.      * @since JDK1.2
  612.      */
  613.     public boolean isHidden() {
  614.     SecurityManager security = System.getSecurityManager();
  615.     if (security != null) {
  616.         security.checkRead(path);
  617.     }
  618.     return ((fs.getBooleanAttributes(this) & FileSystem.BA_HIDDEN) != 0);
  619.     }
  620.  
  621.     /**
  622.      * Returns the time that the file denoted by this abstract pathname was
  623.      * last modified.
  624.      *
  625.      * @return  A <code>long</code> value representing the time the file was
  626.      *          last modified, measured in milliseconds since the epoch
  627.      *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
  628.      *          file does not exist or if an I/O error occurs
  629.      *
  630.      * @throws  SecurityException
  631.      *          If a security manager exists and its <code>{@link
  632.      *          java.lang.SecurityManager#checkRead}</code> method denies
  633.      *          read access to the file
  634.      */
  635.     public long lastModified() {
  636.     SecurityManager security = System.getSecurityManager();
  637.     if (security != null) {
  638.         security.checkRead(path);
  639.     }
  640.     return fs.getLastModifiedTime(this);
  641.     }
  642.  
  643.     /**
  644.      * Returns the length of the file denoted by this abstract pathname.
  645.      *
  646.      * @return  The length, in bytes, of the file denoted by this abstract
  647.      *          pathname, or <code>0L</code> if the file does not exist
  648.      *
  649.      * @throws  SecurityException
  650.      *          If a security manager exists and its <code>{@link
  651.      *          java.lang.SecurityManager#checkRead}</code> method denies
  652.      *          read access to the file
  653.      */
  654.     public long length() {
  655.     SecurityManager security = System.getSecurityManager();
  656.     if (security != null) {
  657.         security.checkRead(path);
  658.     }
  659.     return fs.getLength(this);
  660.     }
  661.  
  662.  
  663.     /* -- File operations -- */
  664.  
  665.     /**
  666.      * Atomically creates a new, empty file named by this abstract pathname if
  667.      * and only if a file with this name does not yet exist.  The check for the
  668.      * existence of the file and the creation of the file if it does not exist
  669.      * are a single operation that is atomic with respect to all other
  670.      * filesystem activities that might affect the file.  This method, in
  671.      * combination with the <code>{@link #deleteOnExit}</code> method, can
  672.      * therefore serve as the basis for a simple but reliable cooperative
  673.      * file-locking protocol.
  674.      *
  675.      * @return  <code>true</code> if the named file does not exist and was
  676.      *          successfully created; <code>false</code> if the named file
  677.      *          already exists
  678.      *
  679.      * @throws  IOException
  680.      *          If an I/O error occurred
  681.      *
  682.      * @throws  SecurityException
  683.      *          If a security manager exists and its <code>{@link
  684.      *          java.lang.SecurityManager#checkWrite}</code> method denies
  685.      *          write access to the file
  686.      *
  687.      * @since JDK1.2
  688.      */
  689.     public boolean createNewFile() throws IOException {
  690.     SecurityManager security = System.getSecurityManager();
  691.     if (security != null) security.checkWrite(path);
  692.     return fs.createFileExclusively(path);
  693.     }
  694.  
  695.     /**
  696.      * Deletes the file or directory denoted by this abstract pathname.  If
  697.      * this pathname denotes a directory, then the directory must be empty in
  698.      * order to be deleted.
  699.      *
  700.      * @return  <code>true</code> if and only if the file or directory is
  701.      *          successfully deleted; <code>false</code> otherwise
  702.      *
  703.      * @throws  SecurityException
  704.      *          If a security manager exists and its <code>{@link
  705.      *          java.lang.SecurityManager#checkDelete}</code> method denies
  706.      *          delete access to the file
  707.      */
  708.     public boolean delete() {
  709.     SecurityManager security = System.getSecurityManager();
  710.     if (security != null) {
  711.         security.checkDelete(path);
  712.     }
  713.     return fs.delete(this);
  714.     }
  715.  
  716.     /**
  717.      * Requests that the file or directory denoted by this abstract pathname
  718.      * be deleted when the virtual machine terminates.  Deletion will be
  719.      * attempted only for normal termination of the virtual machine, as defined
  720.      * by the Java Language Specification (12.9).
  721.      *
  722.      * <p> Once deletion has been requested, it is not possible to cancel the
  723.      * request.  This method should therefore be used with care.
  724.      *
  725.      * @throws  SecurityException
  726.      *          If a security manager exists and its <code>{@link
  727.      *          java.lang.SecurityManager#checkDelete}</code> method denies
  728.      *          delete access to the file
  729.      *
  730.      * @see #delete
  731.      *
  732.      * @since JDK1.2
  733.      */
  734.     public void deleteOnExit() {
  735.     SecurityManager security = System.getSecurityManager();
  736.     if (security != null) {
  737.         security.checkDelete(path);
  738.     }
  739.     fs.deleteOnExit(this);
  740.     }
  741.  
  742.     /**
  743.      * Returns an array of strings naming the files and directories in the
  744.      * directory denoted by this abstract pathname.
  745.      *
  746.      * <p> If this abstract pathname does not denote a directory, then this
  747.      * method returns <code>null</code>.  Otherwise an array of strings is
  748.      * returned, one for each file or directory in the directory.  Names
  749.      * denoting the directory itself and the directory's parent directory are
  750.      * not included in the result.  Each string is a file name rather than a
  751.      * complete path.
  752.      *
  753.      * <p> There is no guarantee that the name strings in the resulting array
  754.      * will appear in any specific order; they are not, in particular,
  755.      * guaranteed to appear in alphabetical order.
  756.      *
  757.      * @return  An array of strings naming the files and directories in the
  758.      *          directory denoted by this abstract pathname.  The array will be
  759.      *          empty if the directory is empty.  Returns <code>null</code> if
  760.      *          this abstract pathname does not denote a directory, or if an
  761.      *          I/O error occurs.
  762.      *
  763.      * @throws  SecurityException
  764.      *          If a security manager exists and its <code>{@link
  765.      *          java.lang.SecurityManager#checkRead}</code> method denies
  766.      *          read access to the directory
  767.      */
  768.     public String[] list() {
  769.     SecurityManager security = System.getSecurityManager();
  770.     if (security != null) {
  771.         security.checkRead(path);
  772.     }
  773.     return fs.list(this);
  774.     }
  775.  
  776.     /**
  777.      * Returns an array of strings naming the files and directories in the
  778.      * directory denoted by this abstract pathname that satisfy the specified
  779.      * filter.  The behavior of this method is the same as that of the
  780.      * <code>{@link #list()}</code> method, except that the strings in the
  781.      * returned array must satisfy the filter.  If the given
  782.      * <code>filter</code> is <code>null</code> then all names are accepted.
  783.      * Otherwise, a name satisfies the filter if and only if the value
  784.      * <code>true</code> results when the <code>{@link
  785.      * FilenameFilter#accept}</code> method of the filter is invoked on this
  786.      * abstract pathname and the name of a file or directory in the directory
  787.      * that it denotes.
  788.      *
  789.      * @param  filter  A filename filter
  790.      *
  791.      * @return  An array of strings naming the files and directories in the
  792.      *          directory denoted by this abstract pathname that were accepted
  793.      *          by the given <code>filter</code>.  The array will be empty if
  794.      *          the directory is empty or if no names were accepted by the
  795.      *          filter.  Returns <code>null</code> if this abstract pathname
  796.      *          does not denote a directory, or if an I/O error occurs.
  797.      *
  798.      * @throws  SecurityException
  799.      *          If a security manager exists and its <code>{@link
  800.      *          java.lang.SecurityManager#checkRead}</code> method denies
  801.      *          read access to the directory
  802.      */
  803.     public String[] list(FilenameFilter filter) {
  804.     String names[] = list();
  805.     if ((names == null) || (filter == null)) {
  806.         return names;
  807.     }
  808.     ArrayList v = new ArrayList();
  809.     for (int i = 0 ; i < names.length ; i++) {
  810.         if (filter.accept(this, names[i])) {
  811.         v.add(names[i]);
  812.         }
  813.     }
  814.     return (String[])(v.toArray(new String[0]));
  815.     }
  816.  
  817.     /**
  818.      * Returns an array of abstract pathnames denoting the files in the
  819.      * directory denoted by this abstract pathname.
  820.      *
  821.      * <p> If this abstract pathname does not denote a directory, then this
  822.      * method returns <code>null</code>.  Otherwise an array of
  823.      * <code>File</code> objects is returned, one for each file or directory in
  824.      * the directory.  Pathnames denoting the directory itself and the
  825.      * directory's parent directory are not included in the result.  Each
  826.      * resulting abstract pathname is constructed from this abstract pathname
  827.      * using the <code>{@link #File(java.io.File, java.lang.String)
  828.      * File(File, String)}</code> constructor.  Therefore if this pathname
  829.      * is absolute then each resulting pathname is absolute; if this pathname
  830.      * is relative then each resulting pathname will be relative to the same
  831.      * directory.
  832.      *
  833.      * <p> There is no guarantee that the name strings in the resulting array
  834.      * will appear in any specific order; they are not, in particular,
  835.      * guaranteed to appear in alphabetical order.
  836.      *
  837.      * @return  An array of abstract pathnames denoting the files and
  838.      *          directories in the directory denoted by this abstract
  839.      *          pathname.  The array will be empty if the directory is
  840.      *          empty.  Returns <code>null</code> if this abstract pathname
  841.      *          does not denote a directory, or if an I/O error occurs.
  842.      *
  843.      * @throws  SecurityException
  844.      *          If a security manager exists and its <code>{@link
  845.      *          java.lang.SecurityManager#checkRead}</code> method denies
  846.      *          read access to the directory
  847.      *
  848.      * @since JDK1.2
  849.      */
  850.     public File[] listFiles() {
  851.     String[] ss = list();
  852.     if (ss == null) return null;
  853.     int n = ss.length;
  854.     File[] fs = new File[n];
  855.     for (int i = 0; i < n; i++) {
  856.         fs[i] = new File(this.path, ss[i]);
  857.     }
  858.     return fs;
  859.     }
  860.  
  861.     /**
  862.      * Returns an array of abstract pathnames denoting the files and
  863.      * directories in the directory denoted by this abstract pathname that
  864.      * satisfy the specified filter.  The behavior of this method is the
  865.      * same as that of the <code>{@link #listFiles()}</code> method, except
  866.      * that the pathnames in the returned array must satisfy the filter.
  867.      * If the given <code>filter</code> is <code>null</code> then all
  868.      * pathnames are accepted.  Otherwise, a pathname satisfies the filter
  869.      * if and only if the value <code>true</code> results when the
  870.      * <code>{@link FilenameFilter#accept}</code> method of the filter is
  871.      * invoked on this abstract pathname and the name of a file or
  872.      * directory in the directory that it denotes.
  873.      *
  874.      * @param  filter  A filename filter
  875.      *
  876.      * @return  An array of abstract pathnames denoting the files and
  877.      *          directories in the directory denoted by this abstract
  878.      *          pathname.  The array will be empty if the directory is
  879.      *          empty.  Returns <code>null</code> if this abstract pathname
  880.      *          does not denote a directory, or if an I/O error occurs.
  881.      *          
  882.      * @throws  SecurityException
  883.      *          If a security manager exists and its <code>{@link
  884.      *          java.lang.SecurityManager#checkRead}</code> method denies
  885.      *          read access to the directory
  886.      *
  887.      * @since JDK1.2
  888.      */
  889.     public File[] listFiles(FilenameFilter filter) {
  890.     String ss[] = list();
  891.     if (ss == null) return null;
  892.     ArrayList v = new ArrayList();
  893.     for (int i = 0 ; i < ss.length ; i++) {
  894.         if ((filter == null) || filter.accept(this, ss[i])) {
  895.         v.add(new File(this.path, ss[i]));
  896.         }
  897.     }
  898.     return (File[])(v.toArray(new File[0]));
  899.     }
  900.  
  901.     /**
  902.      * Returns an array of abstract pathnames denoting the files and
  903.      * directories in the directory denoted by this abstract pathname that
  904.      * satisfy the specified filter.  The behavior of this method is the
  905.      * same as that of the <code>{@link #listFiles()}</code> method, except
  906.      * that the pathnames in the returned array must satisfy the filter.
  907.      * If the given <code>filter</code> is <code>null</code> then all
  908.      * pathnames are accepted.  Otherwise, a pathname satisfies the filter
  909.      * if and only if the value <code>true</code> results when the
  910.      * <code>{@link FilenameFilter#accept}</code> method of the filter is
  911.      * invoked on the pathname.
  912.      *
  913.      * @param  filter  A filename filter
  914.      *
  915.      * @return  An array of abstract pathnames denoting the files and
  916.      *          directories in the directory denoted by this abstract
  917.      *          pathname.  The array will be empty if the directory is
  918.      *          empty.  Returns <code>null</code> if this abstract pathname
  919.      *          does not denote a directory, or if an I/O error occurs.
  920.      *          
  921.      * @throws  SecurityException
  922.      *          If a security manager exists and its <code>{@link
  923.      *          java.lang.SecurityManager#checkRead}</code> method denies
  924.      *          read access to the directory
  925.      *
  926.      * @since JDK1.2
  927.      */
  928.     public File[] listFiles(FileFilter filter) {
  929.     String ss[] = list();
  930.     if (ss == null) return null;
  931.     ArrayList v = new ArrayList();
  932.     for (int i = 0 ; i < ss.length ; i++) {
  933.         File f = new File(this.path, ss[i]);
  934.         if ((filter == null) || filter.accept(f)) {
  935.         v.add(f);
  936.         }
  937.     }
  938.     return (File[])(v.toArray(new File[0]));
  939.     }
  940.  
  941.     /**
  942.      * Creates the directory named by this abstract pathname.
  943.      *
  944.      * @return  <code>true</code> if and only if the directory was
  945.      *          created; <code>false</code> otherwise
  946.      *
  947.      * @throws  SecurityException
  948.      *          If a security manager exists and its <code>{@link
  949.      *          java.lang.SecurityManager#checkWrite}</code> method does not
  950.      *          permit the named directory to be created
  951.      */
  952.     public boolean mkdir() {
  953.     SecurityManager security = System.getSecurityManager();
  954.     if (security != null) {
  955.         security.checkWrite(path);
  956.     }
  957.     return fs.createDirectory(this);
  958.     }
  959.  
  960.     /**
  961.      * Creates the directory named by this abstract pathname, including any
  962.      * necessary but nonexistent parent directories.  Note that if this
  963.      * operation fails it may have succeeded in creating some of the necessary
  964.      * parent directories.
  965.      *
  966.      * @return  <code>true</code> if and only if the directory was created,
  967.      *          along with all necessary parent directories; <code>false</code>
  968.      *          otherwise
  969.      *
  970.      * @throws  SecurityException
  971.      *          If a security manager exists and its <code>{@link
  972.      *          java.lang.SecurityManager#checkWrite}</code> method does not
  973.      *          permit the named directory and all necessary parent directories
  974.      *          and to be created
  975.      */
  976.     public boolean mkdirs() {
  977.     if (exists()) {
  978.         return false;
  979.     }
  980.     if (mkdir()) {
  981.          return true;
  982.      }
  983.     String parent = getParent();
  984.     return (parent != null) && (new File(parent).mkdirs() && mkdir());
  985.     }
  986.  
  987.     /**
  988.      * Renames the file denoted by this abstract pathname.
  989.      *
  990.      * @param  dest  The new abstract pathname for the named file
  991.      * 
  992.      * @return  <code>true</code> if and only if the renaming succeeded;
  993.      *          <code>false</code> otherwise
  994.      *
  995.      * @throws  SecurityException
  996.      *          If a security manager exists and its <code>{@link
  997.      *          java.lang.SecurityManager#checkWrite}</code> method denies
  998.      *          write access to both the old and new pathnames
  999.      */
  1000.     public boolean renameTo(File dest) {
  1001.     SecurityManager security = System.getSecurityManager();
  1002.     if (security != null) {
  1003.         security.checkWrite(path);
  1004.         security.checkWrite(dest.path);
  1005.     }
  1006.     return fs.rename(this, dest);
  1007.     }
  1008.  
  1009.     /**
  1010.      * Sets the last-modified time of the file or directory named by this
  1011.      * abstract pathname.
  1012.      *
  1013.      * <p> All platforms support file-modification times to the nearest second,
  1014.      * but some provide more precision.  The argument will be truncated to fit
  1015.      * the supported precision.  If the operation succeeds and no intervening
  1016.      * operations on the file take place, then the next invocation of the
  1017.      * <code>{@link #lastModified}</code> method will return the (possibly
  1018.      * truncated) <code>time</code> argument that was passed to this method.
  1019.      *
  1020.      * @param  time  The new last-modified time, measured in milliseconds since
  1021.      *               the epoch (00:00:00 GMT, January 1, 1970)
  1022.      *
  1023.      * @returns <code>true</code> if and only if the operation succeeded;
  1024.      *          <code>false</code> otherwise
  1025.      *
  1026.      * @throws  IllegalArgumentException  If the argument is negative
  1027.      *
  1028.      * @throws  SecurityException
  1029.      *          If a security manager exists and its <code>{@link
  1030.      *          java.lang.SecurityManager#checkWrite}</code> method denies
  1031.      *          write access to the named file
  1032.      *
  1033.      * @since JDK1.2
  1034.      */
  1035.     public boolean setLastModified(long time) {
  1036.     if (time < 0) throw new IllegalArgumentException("Negative time");
  1037.     SecurityManager security = System.getSecurityManager();
  1038.     if (security != null) {
  1039.         security.checkWrite(path);
  1040.     }
  1041.     return fs.setLastModifiedTime(this, time);
  1042.     }
  1043.  
  1044.     /**
  1045.      * Marks the file or directory named by this abstract pathname so that
  1046.      * only read operations are allowed.  After invoking this method the file
  1047.      * or directory is guaranteed not to change until it is either deleted or
  1048.      * marked to allow write access.  Whether or not a read-only file or
  1049.      * directory may be deleted depends upon the underlying system.
  1050.      *
  1051.      * @returns <code>true</code> if and only if the operation succeeded;
  1052.      *          <code>false</code> otherwise
  1053.      *
  1054.      * @throws  SecurityException
  1055.      *          If a security manager exists and its <code>{@link
  1056.      *          java.lang.SecurityManager#checkWrite}</code> method denies
  1057.      *          write access to the named file
  1058.      *
  1059.      * @since JDK1.2
  1060.      */
  1061.     public boolean setReadOnly() {
  1062.     SecurityManager security = System.getSecurityManager();
  1063.     if (security != null) {
  1064.         security.checkWrite(path);
  1065.     }
  1066.     return fs.setReadOnly(this);
  1067.     }
  1068.  
  1069.  
  1070.     /* -- Filesystem interface -- */
  1071.  
  1072.     /**
  1073.      * List the available filesystem roots.
  1074.      *
  1075.      * <p> A particular Java platform may support zero or more
  1076.      * hierarchically-organized file systems.  Each file system has a
  1077.      * <code>root</code> directory from which all other files in that file
  1078.      * system can be reached.  Windows platforms, for example, have a root
  1079.      * directory for each active drive; UNIX platforms have a single root
  1080.      * directory, namely <code>"/"</code>.  The set of available filesystem
  1081.      * roots is affected by various system-level operations such the insertion
  1082.      * or ejection of removable media and the disconnecting or unmounting of
  1083.      * physical or virtual disk drives.
  1084.      *
  1085.      * <p> This method returns an array of <code>File</code> objects that
  1086.      * denote the root directories of the available filesystem roots.  It is
  1087.      * guaranteed that the canonical pathname of any file physically present on
  1088.      * the local machine will begin with one of the roots returned by this
  1089.      * method.
  1090.      *
  1091.      * <p> The canonical pathname of a file that resides on some other machine
  1092.      * and is accessed via a remote-filesystem protocol such as SMB or NFS may
  1093.      * or may not begin with one of the roots returned by this method.  If the
  1094.      * pathname of a remote file is syntactically indistinguishable from the
  1095.      * pathname of a local file then it will begin with one of the roots
  1096.      * returned by this method.  Thus, for example, <code>File</code> objects
  1097.      * denoting the root directories of the mapped network drives of a Windows
  1098.      * platform will be returned by this method, while <code>File</code>
  1099.      * objects containing UNC pathnames will not be returned by this method.
  1100.      *
  1101.      * <p> Unlike most methods in this class, this method does not throw
  1102.      * security exceptions.  If a security manager exists and its <code>{@link
  1103.      * java.lang.SecurityManager#checkRead}</code> method denies read access to
  1104.      * a particular root directory, then that directory will not appear in the
  1105.      * result.
  1106.      *
  1107.      * @return  An array of <code>File</code> objects denoting the available
  1108.      *          filesystem roots, or <code>null</code> if the set of roots
  1109.      *          could not be determined.  The array will be empty if there are
  1110.      *          no filesystem roots.
  1111.      *
  1112.      * @since JDK1.2
  1113.      */
  1114.     public static File[] listRoots() {
  1115.     return fs.listRoots();
  1116.     }
  1117.  
  1118.  
  1119.     /* -- Temporary files -- */
  1120.  
  1121.     private static final Object tmpFileLock = new Object();
  1122.  
  1123.     private static int counter = -1; /* Protected by tmpFileLock */
  1124.  
  1125.     private static File generateFile(String prefix, String suffix, File dir)
  1126.     throws IOException
  1127.     {
  1128.     if (counter == -1) {
  1129.         counter = new Random().nextInt() & 0xffff;
  1130.     }
  1131.     counter++;
  1132.     return new File(dir, prefix + Integer.toString(counter) + suffix);
  1133.     }
  1134.  
  1135.     private static String tmpdir; /* Protected by tmpFileLock */
  1136.  
  1137.     private static String getTempDir() {
  1138.     if (tmpdir == null) {
  1139.         GetPropertyAction a = new GetPropertyAction("java.io.tmpdir");
  1140.         tmpdir = ((String) AccessController.doPrivileged(a));
  1141.     }
  1142.     return tmpdir;
  1143.     }
  1144.  
  1145.     private static boolean checkAndCreate(String filename, SecurityManager sm)
  1146.     throws IOException
  1147.     {
  1148.     if (sm != null) {
  1149.         try {
  1150.         sm.checkWrite(filename);
  1151.         } catch (AccessControlException x) {
  1152.         /* Throwing the original AccessControlException could disclose
  1153.            the location of the default temporary directory, so we
  1154.            re-throw a more innocuous SecurityException */
  1155.         throw new SecurityException("Unable to create temporary file");
  1156.         }
  1157.     }
  1158.     return fs.createFileExclusively(filename);
  1159.     }
  1160.  
  1161.     /**
  1162.      * <p> Creates a new empty file in the specified directory, using the
  1163.      * given prefix and suffix strings to generate its name.  If this method
  1164.      * returns successfully then it is guaranteed that:
  1165.      *
  1166.      * <ol>
  1167.      * <li> The file denoted by the returned abstract pathname did not exist
  1168.      *      before this method was invoked, and
  1169.      * <li> Neither this method nor any of its variants will return the same
  1170.      *      abstract pathname again in the current invocation of the virtual
  1171.      *      machine.
  1172.      * </ol>
  1173.      *
  1174.      * This method provides only part of a temporary-file facility.  To arrange
  1175.      * for a file created by this method to be deleted automatically, use the
  1176.      * <code>{@link #deleteOnExit}</code> method.
  1177.      *
  1178.      * <p> The <code>prefix</code> argument must be at least three characters
  1179.      * long.  It is recommended that the prefix be a short, meaningful string
  1180.      * such as <code>"hjb"</code> or <code>"mail"</code>.  The
  1181.      * <code>suffix</code> argument may be <code>null</code>, in which case the
  1182.      * suffix <code>".tmp"</code> will be used.
  1183.      *
  1184.      * <p> To create the new file, the prefix and the suffix may first be
  1185.      * adjusted to fit the limitations of the underlying platform.  If the
  1186.      * prefix is too long then it will be truncated, but its first three
  1187.      * characters will always be preserved.  If the suffix is too long then it
  1188.      * too will be truncated, but if it begins with a period character
  1189.      * (<code>'.'</code>) then the period and the first three characters
  1190.      * following it will always be preserved.  Once these adjustments have been
  1191.      * made the name of the new file will be generated by concatenating the
  1192.      * prefix, five or more internally-generated characters, and the suffix.
  1193.      *
  1194.      * <p> If the <code>directory</code> argument is <code>null</code> then the
  1195.      * system-dependent default temporary-file directory will be used.  The
  1196.      * default temporary-file directory is specified by the system property
  1197.      * <code>java.io.tmpdir</code>.  On UNIX systems the default value of this
  1198.      * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
  1199.      * Win32 systems it is typically <code>"c:\\temp"</code>.
  1200.      *
  1201.      * @param  prefix     The prefix string to be used in generating the file's
  1202.      *                    name; must be at least three characters long
  1203.      *
  1204.      * @param  suffix     The suffix string to be used in generating the file's
  1205.      *                    name; may be <code>null</code>, in which case the
  1206.      *                    suffix <code>".tmp"</code> will be used
  1207.      *
  1208.      * @param  directory  The directory in which the file is to be created, or
  1209.      *                    <code>null</code> if the default temporary-file
  1210.      *                    directory is to be used
  1211.      *
  1212.      * @return  An abstract pathname denoting a newly-created empty file
  1213.      *
  1214.      * @throws  IllegalArgumentException
  1215.      *          If the <code>prefix</code> argument contains fewer than three
  1216.      *          characters
  1217.      *
  1218.      * @throws  IOException  If a file could not be created
  1219.      *
  1220.      * @throws  SecurityException
  1221.      *          If a security manager exists and its <code>{@link
  1222.      *          java.lang.SecurityManager#checkWrite}</code> method does not
  1223.      *          allow a file to be created
  1224.      *
  1225.      * @since JDK1.2
  1226.      */
  1227.     public static File createTempFile(String prefix, String suffix,
  1228.                       File directory)
  1229.         throws IOException
  1230.     {
  1231.     if (prefix == null) throw new NullPointerException();
  1232.     if (prefix.length() < 3)
  1233.         throw new IllegalArgumentException("Prefix string too short");
  1234.     String s = (suffix == null) ? ".tmp" : suffix;
  1235.     synchronized (tmpFileLock) {
  1236.         if (directory == null) {
  1237.         directory = new File(getTempDir());
  1238.         }
  1239.         SecurityManager sm = System.getSecurityManager();
  1240.         File f;
  1241.         do {
  1242.         f = generateFile(prefix, s, directory);
  1243.         } while (!checkAndCreate(f.getPath(), sm));
  1244.         return f;
  1245.     }
  1246.     }
  1247.  
  1248.     /**
  1249.      * Creates an empty file in the default temporary-file directory, using
  1250.      * the given prefix and suffix to generate its name.  Invoking this method
  1251.      * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
  1252.      * java.lang.String, java.io.File)
  1253.      * createTempFile(prefix, suffix, null)}</code>.
  1254.      *
  1255.      * @param  prefix     The prefix string to be used in generating the file's
  1256.      *                    name; must be at least three characters long
  1257.      *
  1258.      * @param  suffix     The suffix string to be used in generating the file's
  1259.      *                    name; may be <code>null</code>, in which case the
  1260.      *                    suffix <code>".tmp"</code> will be used
  1261.      *
  1262.      * @return  An abstract pathname denoting a newly-created empty file
  1263.      *
  1264.      * @throws  IllegalArgumentException
  1265.      *          If the <code>prefix</code> argument contains fewer than three
  1266.      *          characters
  1267.      *
  1268.      * @throws  IOException  If a file could not be created
  1269.      *
  1270.      * @throws  SecurityException
  1271.      *          If a security manager exists and its <code>{@link
  1272.      *          java.lang.SecurityManager#checkWrite}</code> method does not
  1273.      *          allow a file to be created
  1274.      *
  1275.      * @since JDK1.2
  1276.      */
  1277.     public static File createTempFile(String prefix, String suffix)
  1278.     throws IOException
  1279.     {
  1280.     return createTempFile(prefix, suffix, null);
  1281.     }
  1282.  
  1283.  
  1284.     /* -- Basic infrastructure -- */
  1285.  
  1286.     /**
  1287.      * Compares two abstract pathnames lexicographically.  The ordering
  1288.      * defined by this method depends upon the underlying system.  On UNIX
  1289.      * systems, alphabetic case is significant in comparing pathnames; on Win32
  1290.      * systems it is not.
  1291.      *
  1292.      * @param   pathname  The abstract pathname to be compared to this abstract
  1293.      *                    pathname
  1294.      * 
  1295.      * @return  Zero if the argument is equal to this abstract pathname, a
  1296.      *        value less than zero if this abstract pathname is
  1297.      *        lexicographically less than the argument, or a value greater
  1298.      *        than zero if this abstract pathname is lexicographically
  1299.      *        greater than the argument
  1300.      *
  1301.      * @since   JDK1.2
  1302.      */
  1303.     public int compareTo(File pathname) {
  1304.     return fs.compare(this, pathname);
  1305.     }
  1306.  
  1307.     /**
  1308.      * Compares this abstract pathname to another object.  If the other object
  1309.      * is an abstract pathname, then this function behaves like <code>{@link
  1310.      * #compareTo(File)}</code>.  Otherwise, it throws a
  1311.      * <code>ClassCastException</code>, since abstract pathnames can only be
  1312.      * compared to abstract pathnames.
  1313.      *
  1314.      * @param   o  The <code>Object</code> to be compared to this abstract
  1315.      *             pathname
  1316.      *
  1317.      * @return  If the argument is an abstract pathname, returns zero
  1318.      *          if the argument is equal to this abstract pathname, a value
  1319.      *          less than zero if this abstract pathname is lexicographically
  1320.      *          less than the argument, or a value greater than zero if this
  1321.      *          abstract pathname is lexicographically greater than the
  1322.      *          argument
  1323.      *
  1324.      * @throws  <code>ClassCastException</code> if the argument is not an
  1325.      *        abstract pathname
  1326.      *
  1327.      * @see     java.lang.Comparable
  1328.      * @since   JDK1.2
  1329.      */
  1330.     public int compareTo(Object o) {
  1331.     return compareTo((File)o);
  1332.     }
  1333.  
  1334.     /**
  1335.      * Tests this abstract pathname for equality with the given object.
  1336.      * Returns <code>true</code> if and only if the argument is not
  1337.      * <code>null</code> and is an abstract pathname that denotes the same file
  1338.      * or directory as this abstract pathname.  Whether or not two abstract
  1339.      * pathnames are equal depends upon the underlying system.  On UNIX
  1340.      * systems, alphabetic case is significant in comparing pathnames; on Win32
  1341.      * systems it is not.
  1342.      *
  1343.      * @param   obj   The object to be compared with this abstract pathname
  1344.      *
  1345.      * @return  <code>true</code> if and only if the objects are the same;
  1346.      *          <code>false</code> otherwise
  1347.      */
  1348.     public boolean equals(Object obj) {
  1349.     if ((obj != null) && (obj instanceof File)) {
  1350.         return compareTo((File)obj) == 0;
  1351.     }
  1352.     return false;
  1353.     }
  1354.  
  1355.     /**
  1356.      * Computes a hash code for this abstract pathname.  Because equality of
  1357.      * abstract pathnames is inherently system-dependent, so is the computation
  1358.      * of their hash codes.  On UNIX systems, the hash code of an abstract
  1359.      * pathname is equal to the exclusive <em>or</em> of its pathname string
  1360.      * and the decimal value <code>1234321</code>.  On Win32 systems, the hash
  1361.      * code is equal to the exclusive <em>or</em> of its pathname string,
  1362.      * convered to lower case, and the decimal value <code>1234321</code>.
  1363.      *
  1364.      * @return  A hash code for this abstract pathname
  1365.      */
  1366.     public int hashCode() {
  1367.     return fs.hashCode(this);
  1368.     }
  1369.  
  1370.     /**
  1371.      * Returns the pathname string of this abstract pathname.  This is just the
  1372.      * string returned by the <code>{@link #getPath}</code> method.
  1373.      *
  1374.      * @return  The string form of this abstract pathname
  1375.      */
  1376.     public String toString() {
  1377.     return getPath();
  1378.     }
  1379.  
  1380.     /**
  1381.      * WriteObject is called to save this filename.
  1382.      * The separator character is saved also so it can be replaced
  1383.      * in case the path is reconstituted on a different host type.
  1384.      */
  1385.     private synchronized void writeObject(java.io.ObjectOutputStream s)
  1386.         throws IOException
  1387.     {
  1388.     s.defaultWriteObject();
  1389.     s.writeChar(this.separatorChar); // Add the separator character
  1390.     }
  1391.  
  1392.     /**
  1393.      * readObject is called to restore this filename.
  1394.      * The original separator character is read.  If it is different
  1395.      * than the separator character on this system, then the old seperator
  1396.      * is replaced by the local separator.
  1397.      */
  1398.     private synchronized void readObject(java.io.ObjectInputStream s)
  1399.          throws IOException, ClassNotFoundException
  1400.     {
  1401.     s.defaultReadObject();
  1402.     char sep = s.readChar(); // read the previous seperator char
  1403.     if (sep != separatorChar)
  1404.         this.path = this.path.replace(sep, separatorChar);
  1405.     this.path = fs.normalize(this.path);
  1406.     this.prefixLength = fs.prefixLength(this.path);
  1407.     }
  1408.  
  1409.     /** use serialVersionUID from JDK 1.0.2 for interoperability */
  1410.     private static final long serialVersionUID = 301077366599181567L;
  1411.  
  1412. }
  1413.